package com.yhy.common.log.handler;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.yhy.common.core.result.Result;
import com.yhy.common.log.enums.RequestTypeEnum;
import com.yhy.common.log.event.TrackLogEvent;
import com.yhy.common.log.model.TrackLog;
import com.yhy.common.log.util.AccessLogUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.scheduling.annotation.Async;

import javax.servlet.http.HttpServletRequest;
import java.util.Objects;

/**
 * @author Jax
 */
@Slf4j
@RequiredArgsConstructor
public class AccessLogHandler {

    final ApplicationEventPublisher publisher;

    @Async
    public void process(RequestTypeEnum type, HttpServletRequest request, ProceedingJoinPoint point, Object result) {
        TrackLog trackLog = AccessLogUtil.buildTrackLogBasicInfo(request, point, type);

        if (result instanceof ResponseEntity) {
            result = ((ResponseEntity<?>) result).getBody();
        }

        if (Objects.nonNull(result) && !(result instanceof Result)) {
            result = Result.ok(result);
        }
        Result<?> body = JSONUtil.toBean(JSONUtil.toJsonStr(result), Result.class);
        BeanUtil.copyProperties(body, trackLog);
        trackLog.setResponseBody(body);

        // 非查询接口发送一个系统事件，后边如果需要做日志保存可以直接做监听
        if (!StrUtil.equalsIgnoreCase(request.getMethod(), HttpMethod.GET.toString())) {
            publisher.publishEvent(new TrackLogEvent(trackLog));
        }

        if (log.isDebugEnabled()) {
            final String traceLog = AccessLogUtil.getTrackLogString(trackLog, type);
            if (trackLog.isSuccess()) {
                log.debug("♦♦♦ SUCCESS [{}] : {}", trackLog.getRequestUri(), traceLog);
            } else {
                log.error("♦♦♦ FAILURE [{}] : {}", trackLog.getRequestUri(), traceLog);
            }
        }
    }
}
